package org.infodavid.common.impl.services.security;

import javax.persistence.PersistenceException;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.infodavid.common.persistence.IDataObject;
import org.infodavid.common.services.IEntityService.IInterceptor;
import org.infodavid.common.services.IEntityService.IInterceptorEvent;
import org.infodavid.common.services.exceptions.ServiceException;

/**
 * The Class InterceptorAdapter.
 * @param <T>The type of the entity
 */
public class InterceptorAdapter<T extends IDataObject<Long>> implements IInterceptor<T> {
	/** The Constant log. */
	private static final Log LOGGER = LogFactory.getLog(InterceptorAdapter.class);

	/** The next. */
	private IInterceptor<T> next = null;

	/*
	 * See super class or interface. (non-Javadoc)
	 * @see org.infodavid.common.services.IEntityService.IInterceptor#getNext()
	 */
	public IInterceptor<T> getNext() {
		return next;
	}

	/*
	 * See super class or interface. (non-Javadoc)
	 * @see
	 * org.infodavid.common.services.IEntityService.IInterceptor#setNext(org.infodavid.common.services
	 * .IEntityService.IInterceptor)
	 */
	public void setNext(final IInterceptor<T> value) {
		if (value == this) {
			LOGGER.warn("It is not possible to set the next interceptor using the current one");
		}
		else {
			next = value;
		}
	}

	/*
	 * See super class or interface. (non-Javadoc)
	 * @see org.infodavid.common.services.IEntityService.IInterceptor#add(org.infodavid.common.services.
	 * IEntityService.IInterceptor)
	 */
	public void add(final IInterceptor<T> value) {
		if (value == this) {
			LOGGER.warn("It is not possible to add an interceptor using the current one");
		}
		else if (next == null || next == this) {
			next = value;
		}
		else {
			next.add(value);
		}
	}

	/*
	 * See super class or interface. (non-Javadoc)
	 * @see
	 * org.infodavid.common.services.IEntityService.IInterceptor#remove(org.infodavid.common.services.
	 * IEntityService.IInterceptor)
	 */
	public void remove(final IInterceptor<T> value) {
		if (value == this) {
			LOGGER.warn("It is not possible to remove an interceptor using the current one");
		}
		else if (next == value) {
			next = null;
		}
		else if (next != this) {
			next.remove(value);
		}
	}

	/*
	 * See super class or interface. (non-Javadoc)
	 * @see org.infodavid.common.services.IEntityService.IInterceptor#getInterceptor(java.lang.Class)
	 */
	@SuppressWarnings("rawtypes")
	public IInterceptor<T> getInterceptor(final Class<? extends IInterceptor> type) {
		IInterceptor<T> result;
		if (type.isInstance(this)) {
			result = this;
		}
		else if (next == null) {
			result = null;
		}
		else {
			result = next.getInterceptor(type);
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * @see
	 * org.infodavid.common.services.IEntityService.IInterceptor#preExecute(org.infodavid.common.services
	 * .IEntityService.IInterceptorEvent)
	 */
	public void preExecute(final IInterceptorEvent event) throws PersistenceException, ServiceException {}

	/*
	 * (non-Javadoc)
	 * @see
	 * org.infodavid.common.services.IEntityService.IInterceptor#postExecute(org.infodavid.common.services
	 * .IEntityService.IInterceptorEvent)
	 */
	public void postExecute(final IInterceptorEvent event) throws PersistenceException, ServiceException {}
}
